#ifndef GULLENGINE_VECTOR3D_H
#define GULLENGINE_VECTOR3D_H

#include <iostream>


namespace gull {
    namespace core{
        
        class Vector3D
        {
            
        public:
            static void testClass();
            
            Vector3D(double x = 0.0, double y = 0.0, double z = 0.0);
            Vector3D(const Vector3D& v);
            ~Vector3D();
            
            inline double x() const;
            inline double y() const;
            inline double z() const;
            
            Vector3D operator-() const;
            inline double& operator[](unsigned int indice);
            inline double operator[](unsigned int indice) const;
            
            Vector3D operator+(const Vector3D& v) const;
            Vector3D operator-(const Vector3D& v) const;
            Vector3D operator/(const Vector3D& v) const;
            Vector3D operator/(double a) const;
            Vector3D operator*(double a) const;
            Vector3D& operator=(const Vector3D& v);
            Vector3D& operator*=(double a);
            Vector3D& operator/=(const Vector3D& v);
            Vector3D& operator/=(double a);
            Vector3D& operator+=(const Vector3D& v);
            Vector3D& operator-=(const Vector3D& v);
            
            bool operator== (const Vector3D& v) const;
            bool operator!= (const Vector3D& v) const;
            
            double length() const;
            const Vector3D& normalize();
            double dot(const Vector3D& v) const;
            Vector3D cross(const Vector3D& v) const;
            
            
          
        protected:
            double m_x, m_y, m_z;
            
        };
        
        double& Vector3D::operator[](unsigned int indice)
        {
            double* v[] = {&m_x, &m_y, &m_z};
            return *(v[indice]);
        }
        
        
        double Vector3D::operator[](unsigned int indice) const
        {
            const double*v[] = {&m_x, &m_y, &m_z};
            return *(v[indice]);
        }

        
        double Vector3D::x() const {return m_x;}
        double Vector3D::y() const {return m_y;}
        double Vector3D::z() const {return m_z;}
        
    }
}

extern std::ostream& operator<<(std::ostream& o, const gull::core::Vector3D& v);

#endif